home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n03 / ucrasm.asc < prev    next >
Encoding:
Text File  |  1992-01-24  |  9.7 KB  |  346 lines

  1. _THE UCR STANDARD ASSEMBLY LANGUAGE LIBRARY_
  2. by Randall Hyde
  3.  
  4.  
  5.  
  6. [LISTING ONE]
  7.  
  8. Printf      macro
  9. ; The following extrn declaration only occurs if this is the first time
  10. ; printf appears in the source file.
  11. ;
  12.         ifndef  sl_printf
  13. stdlib      segment para public 'slcode'
  14.         extrn   sl_printf:far
  15. stdlib      ends                
  16.         endif
  17. ;
  18. ; Perform the call to the actual sl_printf routine:
  19.         call    far ptr sl_printf
  20.         endm
  21. ;
  22.  
  23.  
  24. [LISTING TWO]
  25.  
  26. ;****************************************************************************
  27. ; TS: A "Text Statistics" package which demonstrates the use of the UCR
  28. ;   Standard Library Package.
  29. ; Note: The purpose of this program is not to demonstrate blazing fast 
  30. ;   assembly code (it's not particularly fast) but rather to demonstrate how 
  31. ;   easy it is to write assembly code using the standard library and MASM 6.0.
  32. ; Randall Hyde
  33. ;***************************************************************************
  34. ;  The following include must be outside any segment and before the
  35. ;  ZZZZZZSEG segment.  It includes all the macro definitions for the
  36. ;  UCR Standard Library.
  37.         include     stdlib.a    ;Links into the UCR Standard
  38.         includelib  stdlib.lib  ; Library package.
  39. ;
  40. dseg        segment para public 'data'
  41. ;
  42. WordCount   dw  0       ;Holds file word count value
  43. LineCnt     dw  0       ;Holds # of lines in file
  44. ControlCnt  dw  0       ;Counts # of control characters
  45. Punct       dw      0       ;Counts # of punctuation characters
  46. AlphaCnt    dw  0       ;Counts # of alphabetic characters
  47. NumericCnt  dw  0       ;Counts numeric digits in file
  48. Other       dw  0       ;Counts other chars in file
  49. MemorySize  dw  0       ;# of paragraphs of free memory
  50. Chars       dw  0       ;Total number of chars in file
  51. TotalChars  dq  0.0     ;FP version of the above
  52. FileHandle  dw  0       ;STDLIB file handle
  53. Const100    dq  100.0
  54. ;
  55. ; Create some sets to use in this program:
  56.         set CharSet,Alphabetic,Punctuation,Control
  57. ;
  58. ; Character Counter array.  CharCnt [ch] contains the number of "ch"
  59. ; characters appearing in the file.
  60. CharCnt     dw  256 dup (0)
  61. ;
  62. ; Boolean flag to denote in/not in a word:
  63. InWord      db  0
  64. ;
  65. dseg        ends
  66. ;
  67. cseg        segment para public 'code'
  68.         assume  cs:cseg, ds:dseg
  69. ;
  70. ; LESI is a macro which loads a 32-bit immediate value into ES:DI.
  71. lesi        macro   adrs
  72.         mov     di, seg adrs
  73.         mov es, di
  74.         lea di, adrs
  75.         endm
  76. ;
  77. ; ldxi loads a 32-bit immediate value into dx:si:
  78. ldxi        macro   adrs
  79.         mov     dx, seg adrs
  80.         lea si, adrs
  81.         endm
  82. ;
  83. ; Some useful constants-
  84. cr      equ 13
  85. lf      equ 10
  86. EOFError    equ 8
  87. ;
  88.         public  PSP     ;DOS Program Segment Prefix
  89. PSP     dw  ?       ;Needed by StdLib MemInit routine
  90. ;
  91. ; Okay, here's the main program which does the job:
  92. TS      proc
  93.         mov cs:PSP, es      ;Save pgm seg prefix
  94.         mov ax, seg dseg        ;Set up the segment registers
  95.         mov ds, ax
  96.         mov es, ax
  97. ;
  98. ; Initialize the memory manager, giving all free memory to the heap.
  99.         mov dx, 0
  100.         meminit
  101.         mov MemorySize, cx  ;Save # of available paragraphs.
  102. ;
  103. ; Set up the character sets:
  104. ;  First, build the Alphabetic set:
  105.         mov al, "A"
  106.         mov ah, "Z"
  107.         lesi    Alphabetic
  108.         RangeSet
  109.         AddStrL
  110.         db  "abcdefghijklmnopqrstuvwxyz",0
  111. ;
  112. ; Create the set with the punctuation characters:
  113.         lesi    Punctuation
  114.         AddStrL
  115.         db  "!@#$%^&*()_-+={[}]|\':;<,>.?/~`", '"', 0
  116. ;
  117. ; Create the control character set:
  118.         lesi    Control
  119.         mov al,0
  120.         mov ah, 1fh
  121.         RangeSet
  122.         mov al, 7fh
  123.         AddChar
  124. ;
  125. ; Print the amount of available memory and prompt the user to enter a file name.
  126.         printf
  127.         db  "Text Statistics Program",cr,lf
  128.         db  "There are %d paragraphs of memory available",cr,lf
  129.         db  lf
  130.         db  "Enter a filename:",0
  131.         dd  MemorySize
  132. ;
  133.         getsm               ;Get the filename.
  134. ;
  135. ; Open the file.
  136.         mov al, 0           ;Open for reading.
  137.         fopen               ;Open the file.
  138.         jnc GoodOpen
  139. ;
  140. ; If the carry flag comes back set, we've got an error, print an appropriate
  141. ; message and quit:
  142.         print
  143.         db  "DOS error #",0
  144.         puti                ;Error code is in AX.
  145.         putcr
  146.         jmp Return2DOS
  147. ;
  148. ; If the carry flag comes back clear, we've successfully opened the file. AX 
  149. ; contains the STDLIB filehandle, ES:DI still points at the filename
  150. ; allocated on the heap:
  151. GoodOpen:   mov FileHandle, AX      ;Save STDLIB file handle.
  152.         print
  153.         db  "Computing text statistics for ",0
  154.         puts                ;Print filename
  155.         free                ;Dispose of space on heap
  156.         putcr
  157.         putcr
  158. ;
  159. ; The following loops check for transitions between words and delimiters. Each 
  160. ; time we go from "not a word" -> "word" this code bumps up word count by one.
  161.         mov ax, FileHandle
  162.         fReadOn
  163. ;
  164. TSLoop:     getc
  165.         jnc NoError
  166.         jmp ReadError
  167. ;
  168. ; See if the character is alphabetic
  169. NoError:    lesi    Alphabetic      ;Set contains A-Z, a-z
  170.         Member
  171.         jz  NotAlphabetic
  172.         inc AlphaCnt
  173.         jmp StatDone
  174. ;
  175. ; See if the character is a digit:
  176. NotAlphabetic:  cmp al, "0"
  177.         jb  NotNumeric
  178.         cmp al, "9"
  179.         ja  NotNumeric
  180.         inc NumericCnt
  181.         jmp StatDone
  182. ;
  183. ; See if the character is a punctuation character
  184. NotNumeric: lesi    Punctuation
  185.         Member
  186.         jz  NotPunctuation
  187.         inc Punct
  188.         jmp StatDone
  189. ;
  190. ; See if this is a control character:
  191. NotPunctuation: lesi    Control
  192.         Member
  193.         jz  NotControl
  194.         inc ControlCnt
  195.         jmp StatDone
  196. ;
  197. NotControl: inc Other
  198. StatDone:       mov bl, al      ;Use char as index into CharCnt
  199.         mov bh, 0
  200.         shl bx, 1       ;Convert word index to byte index
  201.         inc CharCnt [bx]
  202. ;
  203. ; Count lines and characters here:
  204.         cmp al, lf
  205.         jne NotNewLine
  206.         inc LineCnt
  207. ;
  208. NotNewLine:     inc Chars
  209. ; Count words down here
  210.         cmp InWord, 0       ;See if we're in a word.
  211.         je  NotInAWord
  212.         cmp al, " "
  213.         ja  WCDone
  214.         mov InWord, 0       ;Just left a word
  215.         jmp WCDone
  216. ;
  217. NotInAWord: cmp al, " "
  218.         jbe WCDone
  219.         mov InWord, 1       ;Just entered a word
  220.         inc WordCount
  221. ;
  222. WCDone:
  223. ;
  224. ; Okay, or the current character into the character set so we can keep
  225. ; track of the characters which appear in this file.
  226.         lesi    CharSet
  227.         AddChar
  228.         jmp TSLoop
  229. ;
  230. ; Come down here on EOF or other read error.
  231. ReadError:  cmp ax, EOFError
  232.         je  Quit
  233.         print
  234.         db  "DOS Error ",0
  235.         puti
  236.         putcr
  237.         jmp Return2DOS
  238. ;
  239. ; Return to DOS.
  240. Quit:       freadoff
  241.         mov ax, FileHandle
  242.         fclose
  243.         printf
  244.         db  cr,lf,lf
  245.         db  "Number of words in this file is %d",cr,lf
  246.         db  "Number of lines in this file is %d",cr,lf
  247.         db  "Number of control characters is %d",cr,lf
  248.         db  "Number of punctuation characters is %d",cr,lf
  249.         db  "Number of alphabetic characters is %d",cr,lf
  250.         db  "Number of numeric characters is %d",cr,lf
  251.         db  "Number of other characters is %d",cr,lf
  252.         db  "Total number of characters is %d",cr,lf
  253.         db  lf, 0
  254.         dd  WordCount,LineCnt,ControlCnt,Punct
  255.         dd  AlphaCnt,NumericCnt,Other,Chars
  256. ;
  257. ; Print the characters that actually appeared in the file.
  258.         lesi    CharSet
  259. EC64:       mov cx, 64          ;Chars/line on output.
  260. EachChar:   RmvItem
  261.         cmp al, 0
  262.         je  CSDone
  263.         cmp al, " "
  264.         jbe EachChar
  265.         putc
  266.         loop    EachChar
  267.         putcr
  268.         jmp EC64
  269. ;
  270. CSDone:     print
  271.         db  cr,lf,lf
  272.         db  "Press any key to continue:",0
  273.         getc
  274.         putcr
  275.         putcr
  276. ;
  277. ; Now print the statistics for each character:
  278.         mov ax, Chars       ;Get character count,
  279.         utof                ; convert it to a floating
  280.         lesi    TotalChars      ; point value, and save this
  281.         sdfpa               ; value in "TotalChars".
  282. ;
  283. ; Print out each character, the number of occurrences, and the ratio of
  284. ; this character's count to the total number of characters.
  285.         mov bx, " "*2       ;Start output with spaces.
  286. ComputeRatios:  cmp CharCnt[bx], 0
  287.         je  SkipThisChar
  288.         mov ax, bx
  289.         shr ax, 1           ;Convert index to character
  290.         putc                ; and print it.
  291.         print
  292.         db  " = ",0
  293.         mov ax, CharCnt [bx]
  294.         mov cx, 4
  295.         putisize
  296.         print
  297.         db  "  Percentage of total is ",0
  298. ;
  299.         utof
  300. ;
  301. ; Divide by the total number of characters in the file:
  302.         lesi    TotalChars
  303.         ldfpo
  304.         fpdiv
  305. ;
  306. ; Multiply by 100 to get a percentage
  307.         lesi    Const100
  308.         ldfpo
  309.         fpmul
  310. ;
  311. ; Print the ratio:
  312.         mov al, 7
  313.         mov ah, 3
  314.         ftoam
  315.         puts
  316.         free
  317.         print
  318.         db  "%",cr,lf,0
  319. ;
  320. SkipThisChar:   inc bx
  321.         inc bx
  322.         cmp bx, 200h
  323.         jb      ComputeRatios
  324.         putcr
  325. ;
  326. Return2DOS: mov     ah, 4ch
  327.         int     21h
  328. ;
  329. TS      endp
  330. ;
  331. cseg            ends
  332. ;
  333. ; Allocate a reasonable amount of space for the stack (2k).
  334. sseg        segment para stack 'stack'
  335. stk     db  256 dup ("stack   ")
  336. sseg        ends
  337. ;
  338. ; zzzzzzseg must be the last segment that gets loaded into memory!
  339. ; The UCR Standard Library package uses this segment to determine where
  340. ; the end of the program lies.
  341. zzzzzzseg   segment para public 'zzzzzz'
  342. LastBytes   db  16 dup (?)
  343. zzzzzzseg   ends
  344.         end TS
  345.  
  346.